package cn.iocoder.yudao.framework.mybatis.handler;

import cn.iocoder.yudao.framework.datasource.local.ThreadLocalContext;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 * @className: MyMetaObjectHandler
 * @author: tangkh
 * @date: 2023-09-19 17:18
 */
public class MyMetaObjectHandler implements MetaObjectHandler {
    private static final Logger log = LoggerFactory.getLogger(MyMetaObjectHandler.class);
    private JdbcTemplate jdbcTemplate;

    public MyMetaObjectHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void insertFill(MetaObject metaObject) {
        log.debug("start insert fill");
        Object originalFieldValue = this.getFieldValByName("createdTime", metaObject);
        if (originalFieldValue == null) {
            this.setFieldValByName("createdTime", this.getDbNowDate(), metaObject);
        }

        this.setBy("createdBy", metaObject);
        this.updateFill(metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.debug("start update fill");
        Object originalFieldValue = this.getFieldValByName("updatedTime", metaObject);
        if (originalFieldValue == null) {
            this.setFieldValByName("updatedTime", this.getDbNowDate(), metaObject);
        }
        this.setBy("updatedBy", metaObject);
    }

    private void setBy(String fieldName, MetaObject metaObject) {
        Object originalFieldValue = this.getFieldValByName(fieldName, metaObject);
        if (originalFieldValue == null) {
            Object empIdObj = ThreadLocalContext.getAttachment("empId");
            if (empIdObj != null && empIdObj instanceof Integer) {
                Long empId = Long.valueOf(empIdObj.toString());
                this.setFieldValByName(fieldName, empId, metaObject);
            }
        }

    }

    public Date getDbNowDate() {
        Object isThreadLocalHandlerObj = ThreadLocalContext.getAttachment("isThreadLocalHandler");
        boolean isThreadLocalHandler = isThreadLocalHandlerObj != null && "1".equals(isThreadLocalHandlerObj.toString());
        if (isThreadLocalHandler) {
            Object dbNowDateObj = ThreadLocalContext.getAttachment("dbNowDate");
            Object nowDateMillisObj = ThreadLocalContext.getAttachment("nowDateMillis");
            if (dbNowDateObj != null && dbNowDateObj instanceof Date && nowDateMillisObj != null && nowDateMillisObj instanceof Long) {
                Date dbNowDate = (Date)dbNowDateObj;
                Long nowDateMillis = (Long)nowDateMillisObj;
                Long curTime = System.currentTimeMillis() - nowDateMillis;
                if (curTime < 1000L) {
                    return dbNowDate;
                }

                log.warn("数据库取出的时间大于当前时间1秒（{}），重新获取", curTime);
            }
        }

        Date date = covertTime(new Date());
        if (this.jdbcTemplate != null) {
            try {
                Date now = (Date)this.jdbcTemplate.queryForObject("select now()", Date.class);
                if (now != null) {
                    now = covertTime(now);
                    if (isThreadLocalHandler) {
                        ThreadLocalContext.setAttachment("dbNowDate", now);
                        ThreadLocalContext.setAttachment("nowDateMillis", System.currentTimeMillis());
                    }

                    date = now;
                }
            } catch (Exception var8) {
                log.error("获取数据库所在服务器时间失败：{}", var8.getMessage());
            }
        }

        return date;
    }

    private static Date covertTime(Date date) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timestamp now = new Timestamp(date.getTime());
        String str = df.format(now);

        try {
            return df.parse(str);
        } catch (ParseException var5) {
            log.warn("转换日期去掉毫秒异常");
            return date;
        }
    }
}
